package org.example.dataStructure.linkedList;

/**
 * @author yuwl
 * @description 单链表CRUD
 * @since 2024-02-29 15:04
 */
public class SingleLinkedList {

    /**
     * 先初始化一个头节点，头节点不要动，不存放具体数据
     */
    protected HeroNode head = new HeroNode(0, "", "");

    /**
     * 添加节点到单向链表，不考虑编号顺序时
     * 1.找到当前链表的最后节点
     * 2.将最后这个节点的next指向 新的节点
     * @param heroNode
     */
    public void add(HeroNode heroNode) {
        // 因为head节点不能动，因此我们需要一个辅助temp
        HeroNode temp = head;
        // 遍历链表，找到最后
        while (true) {
            // 找到链表最后
            if (temp.next == null) {
                break;
            }
            // 如果没有找到最后，将temp后移
            temp = temp.next;
        }
        // 将最后这个节点的next指向 新的节点
        temp.next = heroNode;
    }

    /**
     * 添加节点到单向链表，根据编号顺序插入
     * 如果编号已存在，则添加失败
     * @param heroNode
     */
    public void addByOrder(HeroNode heroNode) {
        // 因为头节点不能动，因此仍然通过一个辅助节点来帮助找到添加的位置
        // 实际添加的位置为找到的位置的后一个节点
        HeroNode temp = head;
        // 编号已存在标识
        boolean flag = false;

        while (true) {
            // 已经在链表的最后
            if (temp.next == null) {
                break;
            }
            if (temp.next.no > heroNode.no) {
                // 位置找到，就在temp后面插入
                break;
            } else if (temp.next.no == heroNode.no) {
                // 编号已存在标识
                flag = true;
            }
            // 如果没有找到最后，将temp后移
            temp = temp.next;
        }

        if (flag) {
            System.out.printf("准备插入的编号%d已经存在，不能加入\n", heroNode.no);
        } else {
            // 插入到链表中
            heroNode.next = temp.next;
            temp.next = heroNode;
        }
    }

    /**
     * 修改节点信息，根据no编号来修改
     * @param newHeroNode
     */
    public void update(HeroNode newHeroNode) {
        // 判断是否为空
        if (head.next == null) {
            System.out.println("链表为空");
            return;
        }
        // 找到需要修改的节点，根据no编号
        // 定义一个辅助变量
        HeroNode temp = head;
        boolean flag = false;
        while (true) {
            if (temp == null) {
                // 已经遍历完链表
                break;
            }
            if (temp.no == newHeroNode.no) {
                flag = true;
                break;
            }
            // 如果没有找到最后，将temp后移
            temp = temp.next;
        }

        if (flag) {
            temp.name = newHeroNode.name;
            temp.nickName = newHeroNode.nickName;
        } else {
            System.out.printf("没有找到编号%d的节点，不能修改\n", newHeroNode.no);
        }
    }

    /**
     * 删除节点，根据no编号
     * @param no
     */
    public void del(int no) {
        // 头节点不能动，定义一个辅助变量
        HeroNode temp = head;
        boolean flag = false;
        while (true) {
            if (temp.next == null) {
                // 链表最后
                break;
            }
            if (temp.next.no == no) {
                // 找到待删除节点的前一个节点
                flag = true;
                break;
            }
            // 没找到，temp后移
            temp = temp.next;
        }
        if (flag) {
            temp.next = temp.next.next;
        } else {
            System.out.printf("要删除的节点编号%d不存在\n", no);
        }
    }

    /**
     * 遍历链表
     */
    public void list() {
        // 判断是否为空
        if (head.next == null) {
            System.out.println("链表为空");
            return;
        }
        // 头节点不能动，定义一个辅助变量
        HeroNode temp = head.next;
        while (true) {
            System.out.println(temp);
            if (temp.next == null) {
                break;
            }
            // temp后移
            temp = temp.next;
        }
    }

}

class HeroNode {
    protected int no;
    protected String name;
    protected String nickName;
    protected HeroNode next;

    public HeroNode(int no, String name, String nickName) {
        this.no = no;
        this.name = name;
        this.nickName = nickName;
    }

    @Override
    public String toString() {
        return "HeroNode{" +
                "no=" + no +
                ", name='" + name + '\'' +
                ", nickName='" + nickName + '\'' +
                ", next=" + next +
                '}';
    }
}